<template>
	<div class="upload-media-container" :class="{ 'multi-upload': props.multi }">
		<div class="media-list">
			<!-- 文件项列表 -->
			<div
				v-for="(file, index) in files"
				:key="file.FileId || index"
				class="media-item"
				:class="{
					'is-uploading': file.status === 'uploading',
					'is-image': file.isImage,
					'is-file': !file.isImage,
				}"
			>
				<div class="media-wrapper">
					<!-- 图片缩略图 -->
					<div v-if="file.isImage" class="media-content img-container">
						<img v-if="file.url && !file.hasError" :src="file.url" :alt="file.name" @load="onImageLoad(file)" @error="onImageError(file)" />
						<div v-else class="media-placeholder" :class="{ 'error-placeholder': file.hasError }">
							<i class="fa fa-image"></i>
							<span v-if="file.hasError">加载失败</span>
							<span v-else-if="file.status === 'loading'">加载中...</span>
							<span v-else>暂无图片</span>
						</div>
					</div>

					<!-- 文件缩略图 -->
					<div v-else class="media-content file-container">
						<div class="file-thumbnail">
							<i :class="getFileIcon(file.name)"></i>
							<div class="file-ext">{{ getFileExt(file.name) }}</div>
						</div>
						<div class="file-info">
							<div class="file-name" :title="file.name">{{ file.name }}</div>
							<div class="file-size" v-if="file.size">{{ formatBytes(file.size) }}</div>
						</div>
					</div>

					<!-- 遮罩层和操作按钮 -->
					<div class="item-mask">
						<div class="action-icons">
							<!-- 预览按钮 -->
							<div v-if="file.url" class="action-btn preview-btn" @click.stop="onPreview(file)">
								<el-icon><ZoomIn /></el-icon>
							</div>
							<!-- 下载按钮 -->
							<div v-if="file.url && !file.isImage" class="action-btn download-btn" @click.stop="onDownload(file)">
								<el-icon><Download /></el-icon>
							</div>
							<!-- 删除按钮 -->
							<div v-if="!props.disabled" class="action-btn delete-btn" @click.stop="handleRemove(file)">
								<el-icon><Delete /></el-icon>
							</div>
						</div>
					</div>

					<!-- 上传进度遮罩 -->
					<div v-if="file.status === 'uploading' || file.status === 'loading'" class="upload-progress-mask">
						<div class="progress-content">
							<div class="loading-spinner">
								<i class="fa fa-spinner fa-spin"></i>
							</div>
							<span class="progress-text">
								{{ file.status === 'uploading' ? '上传中...' : '加载中...' }}
							</span>
						</div>
					</div>

					<!-- 序号角标 -->
					<div v-if="props.multi && files.length > 1" class="corner-mark">{{ index + 1 }}</div>

					<!-- 文件类型标签 -->
					<div class="file-type-badge" :class="{ 'is-image': file.isImage }">
						{{ file.isImage ? '图片' : '文件' }}
					</div>
				</div>
			</div>

			<!-- 上传按钮 -->
			<el-upload
				v-if="!props.disabled && (files?.length === 0 || (props.multi && files.length < props.limit))"
				ref="uploadRef"
				:action="'/api/_file/Upload'"
				:on-success="onSuccess"
				:on-progress="onProgress"
				:on-error="onError"
				:before-upload="beforeUpload"
				:on-exceed="onExceed"
				:headers="header"
				:file-list="[]"
				:show-file-list="false"
				:disabled="props.disabled"
				:multiple="props.multi"
				:accept="acceptTypes"
				:limit="props.limit"
				:auto-upload="true"
				class="upload-trigger"
			>
				<div class="upload-btn">
					<i class="fa fa-plus"></i>
					<span class="upload-text">上传文件</span>
					<span v-if="props.multi" class="upload-count">{{ files?.length || 0 }}/{{ props.limit }}</span>
				</div>
			</el-upload>

			<!-- 禁用状态下的占位符 -->
			<div v-if="props.disabled && files?.length === 0" class="upload-placeholder">
				<div class="placeholder-content">
					<i class="fa fa-folder-open"></i>
					<span>暂无文件</span>
				</div>
			</div>
		</div>

		<!-- 预览对话框 -->
		<el-dialog
			v-model="previewOpen"
			append-to-body
			:width="previewDialogWidth"
			:title="previewTitle"
			:fullscreen="previewFullscreen"
			class="file-preview-dialog"
		>
			<div class="preview-container" :class="{ 'fullscreen-preview': previewFullscreen }">
				<!-- 图片预览 -->
				<img v-if="previewType === 'image'" :src="previewUrl" alt="Preview" class="preview-image" />

				<!-- PDF 预览 -->
				<iframe v-else-if="previewType === 'pdf'" :src="previewUrl" class="preview-iframe" frameborder="0"></iframe>

				<!-- Office 文档预览 (使用微软在线预览) -->
				<iframe
					v-else-if="previewType === 'office'"
					:src="`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(previewUrl)}`"
					class="preview-iframe"
					frameborder="0"
				></iframe>

				<!-- 文本文件预览 -->
				<div v-else-if="previewType === 'text'" class="preview-text">
					<pre v-if="previewContent">{{ previewContent }}</pre>
					<div v-else class="loading-text">
						<i class="fa fa-spinner fa-spin"></i>
						<span>加载中...</span>
					</div>
				</div>

				<!-- 视频预览 -->
				<video v-else-if="previewType === 'video'" :src="previewUrl" controls class="preview-video"></video>

				<!-- 音频预览 -->
				<audio v-else-if="previewType === 'audio'" :src="previewUrl" controls class="preview-audio"></audio>

				<!-- 不支持预览的文件类型 -->
				<div v-else class="preview-unsupported">
					<div class="unsupported-content">
						<i class="fa fa-file-o fa-3x"></i>
						<p>该文件类型不支持在线预览</p>
						<p class="file-name">{{ previewFileName }}</p>
						<el-button type="primary" @click="onDownload(currentPreviewFile)">
							<el-icon><Download /></el-icon>
							下载文件
						</el-button>
					</div>
				</div>
			</div>

			<template #footer>
				<div class="preview-footer">
					<el-button @click="previewFullscreen = !previewFullscreen">
						{{ previewFullscreen ? '退出全屏' : '全屏显示' }}
					</el-button>
					<el-button type="primary" @click="onDownload(currentPreviewFile)">
						<el-icon><Download /></el-icon>
						下载
					</el-button>
					<el-button @click="previewOpen = false">关闭</el-button>
				</div>
			</template>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { Local } from '/@/utils/storage';
import fileApi from '/@/api/file';
import { ElDialog, ElMessage, ElMessageBox } from 'element-plus';
import { ZoomIn, Delete, Download } from '@element-plus/icons-vue';

const emit = defineEmits(['refresh', 'update:modelValue', 'update:deletedFiles', 'upload-status']);
const uploadRef = ref();
const files = ref<any[]>([]);
const isUpdatingFromUpload = ref(false);

// 定义父组件传过来的值
const props = defineProps({
	multi: Boolean,
	disabled: Boolean,
	modelValue: null,
	deletedFiles: null,
	maxSize: { type: Number, default: 50 }, // 最大文件大小(MB)
	limit: { type: Number, default: 10 }, // 文件数量限制
	allowedTypes: { type: Array as any, default: () => ['*'] }, // 允许的文件类型，默认所有
	imageOnly: Boolean, // 仅允许图片
	fileOnly: Boolean, // 仅允许文件
});

const fileValue = computed({
	get() {
		return props.modelValue;
	},
	set(value) {
		emit('update:modelValue', value);
	},
});

const deletedFiles = computed<any[]>({
	get() {
		return props.deletedFiles ?? [];
	},
	set(value) {
		emit('update:deletedFiles', value);
	},
});

// 预览相关状态
const previewOpen = ref(false);
const previewUrl = ref('');
const previewType = ref(''); // 预览类型：image, pdf, office, text, video, audio, unsupported
const previewContent = ref(''); // 文本内容
const previewFileName = ref('');
const previewFullscreen = ref(false);
const currentPreviewFile = ref<any>(null);

// 预览对话框宽度
const previewDialogWidth = computed(() => {
	if (previewType.value === 'text') return '900px';
	if (previewType.value === 'pdf' || previewType.value === 'office') return '90%';
	return '800px';
});

// 预览标题
const previewTitle = computed(() => {
	const typeMap: Record<string, string> = {
		image: '图片预览',
		pdf: 'PDF预览',
		office: '文档预览',
		text: '文本预览',
		video: '视频预览',
		audio: '音频预览',
		unsupported: '文件信息',
	};
	return typeMap[previewType.value] || '文件预览';
});

const header = computed(() => {
	return { Authorization: `Bearer ${Local.get('token')}` };
});

// 计算accept属性
const acceptTypes = computed(() => {
	if (props.imageOnly) return 'image/*';
	if (props.fileOnly) return '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar';
	if (!props.allowedTypes || props.allowedTypes.includes('*')) return '';
	return props.allowedTypes.join(',');
});

// 计算是否有文件正在上传
const isUploading = computed(() => {
	return files.value.some((file) => file.status === 'uploading' || file.status === 'loading');
});

// 监听上传状态变化并发出事件
watch(
	isUploading,
	(newStatus) => {
		emit('upload-status', newStatus);
	},
	{ immediate: true }
);

/**
 * 判断文件是否为图片
 */
const isImageFile = (filename: string): boolean => {
	const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.ico'];
	const ext = filename.toLowerCase().substring(filename.lastIndexOf('.'));
	return imageExts.includes(ext);
};

/**
 * 获取文件扩展名
 */
const getFileExt = (filename: string): string => {
	if (!filename) return '';
	const ext = filename.substring(filename.lastIndexOf('.') + 1);
	return ext.toUpperCase();
};

/**
 * 获取文件图标
 */
const getFileIcon = (filename: string): string => {
	const ext = getFileExt(filename).toLowerCase();
	const iconMap: Record<string, string> = {
		pdf: 'fa fa-file-pdf',
		doc: 'fa fa-file-word',
		docx: 'fa fa-file-word',
		xls: 'fa fa-file-excel',
		xlsx: 'fa fa-file-excel',
		ppt: 'fa fa-file-powerpoint',
		pptx: 'fa fa-file-powerpoint',
		txt: 'fa fa-file-text',
		zip: 'fa fa-file-archive',
		rar: 'fa fa-file-archive',
		'7z': 'fa fa-file-archive',
		mp4: 'fa fa-file-video',
		avi: 'fa fa-file-video',
		mp3: 'fa fa-file-audio',
		wav: 'fa fa-file-audio',
	};
	return iconMap[ext] || 'fa fa-file';
};

/**
 * 格式化文件大小
 */
const formatBytes = (bytes: number): string => {
	if (!bytes) return '';
	const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
	const i = Math.floor(Math.log(bytes) / Math.log(1024));
	return `${(bytes / Math.pow(1024, i)).toFixed(1)}${sizes[i]}`;
};

// 文件名缓存
const fileNameCache = new Map<string, string>();

// 监听文件值变化
watch(
	fileValue,
	async () => {
		// 防止上传过程中的循环更新
		if (isUpdatingFromUpload.value) {
			return;
		}

		if (!fileValue.value) {
			files.value = [];
			return;
		}

		if (!files.value) {
			files.value = [];
		}

		if (!props.multi) {
			let fv = files.value && files.value.length > 0 ? files.value[0].FileId : null;
			if (props.modelValue !== fv) {
				files.value = [];
				if (props.modelValue) {
					try {
						let filename = fileNameCache.get(props.modelValue) || (await fileApi().getName(props.modelValue));
						if (!fileNameCache.has(props.modelValue)) {
							fileNameCache.set(props.modelValue, filename);
						}
						const isImage = isImageFile(filename);
						files.value = [
							{
								name: filename,
								url: isImage ? `/api/_file/getfile/${props.modelValue}?width=150&height=150` : `/api/_file/getfile/${props.modelValue}`,
								FileId: props.modelValue,
								isImage: isImage,
							},
						];
					} catch (error) {
						console.error('加载文件失败:', error);
					}
				}
			}
		} else {
			// 多文件模式
			if (!props.modelValue || !Array.isArray(props.modelValue) || props.modelValue.length === 0) {
				files.value = [];
				return;
			}

			const newFiles = [];

			for (let i = 0; i < props.modelValue.length; i++) {
				const item = props.modelValue[i];
				if (!item || !item.FileId) {
					continue;
				}

				const fileId = typeof item.FileId === 'string' ? item.FileId : String(item.FileId);
				if (!fileId || fileId === 'undefined' || fileId === 'null') {
					continue;
				}

				const existingFile = files.value.find((f) => f.FileId === fileId);

				if (existingFile) {
					newFiles.push(existingFile);
				} else {
					try {
						let filename = fileNameCache.get(fileId) || (await fileApi().getName(fileId));
						if (!fileNameCache.has(fileId)) {
							fileNameCache.set(fileId, filename);
						}
						const isImage = isImageFile(filename);
						let nv = {
							name: filename,
							url: isImage ? `/api/_file/getfile/${fileId}?width=150&height=150` : `/api/_file/getfile/${fileId}`,
							FileId: fileId,
							keyID: item.ID,
							Order: i,
							status: 'success',
							isImage: isImage,
						};
						newFiles.push(nv);
					} catch (error) {
						console.error('获取文件名失败:', error, '文件ID:', fileId);
						let nv = {
							name: '未知文件',
							url: '',
							FileId: fileId,
							keyID: item.ID,
							Order: i,
							status: 'error',
							hasError: true,
							isImage: false,
						};
						newFiles.push(nv);
					}
				}
			}

			files.value = newFiles;
		}
	},
	{ immediate: true }
);

/**
 * 获取文件预览类型
 */
const getPreviewType = (filename: string): string => {
	if (!filename) return 'unsupported';

	const ext = filename.toLowerCase().substring(filename.lastIndexOf('.'));

	// 图片
	const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.ico'];
	if (imageExts.includes(ext)) return 'image';

	// PDF
	if (ext === '.pdf') return 'pdf';

	// Office 文档
	const officeExts = ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'];
	if (officeExts.includes(ext)) return 'office';

	// 文本文件
	const textExts = ['.txt', '.json', '.xml', '.html', '.css', '.js', '.ts', '.vue', '.md', '.log', '.csv'];
	if (textExts.includes(ext)) return 'text';

	// 视频
	const videoExts = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'];
	if (videoExts.includes(ext)) return 'video';

	// 音频
	const audioExts = ['.mp3', '.wav', '.ogg', '.m4a', '.flac', '.aac'];
	if (audioExts.includes(ext)) return 'audio';

	return 'unsupported';
};

/**
 * 预览文件
 */
const onPreview = async (file: any) => {
	currentPreviewFile.value = file;
	previewFileName.value = file.name || '';
	previewFullscreen.value = false;
	previewContent.value = '';

	// 获取文件 URL
	if (file.FileId) {
		previewUrl.value = `/api/_file/getfile/${file.FileId}`;
	} else {
		previewUrl.value = file.url;
	}

	// 确定预览类型
	previewType.value = getPreviewType(file.name);

	// 如果是文本文件，需要加载内容
	if (previewType.value === 'text') {
		try {
			const response = await fetch(previewUrl.value, {
				headers: header.value,
			});
			previewContent.value = await response.text();
		} catch (error) {
			console.error('Failed to load text file:', error);
			ElMessage.error('文本文件加载失败');
			previewContent.value = '加载失败';
		}
	}

	previewOpen.value = true;
};

/**
 * 下载文件
 */
const onDownload = async (file: any) => {
	if (!file || !file.FileId) {
		ElMessage.error('文件信息不完整');
		return;
	}

	try {
		await fileApi().downloadFile(file.FileId);
		ElMessage.success('下载成功');
	} catch (error) {
		ElMessage.error('下载失败');
		console.error('Download error:', error);
	}
};

/**
 * 上传前验证
 */
const beforeUpload = (file: File) => {
	const isLtMaxSize = file.size / 1024 / 1024 < props.maxSize;

	if (!isLtMaxSize) {
		ElMessage.error(`文件大小不能超过 ${props.maxSize}MB！`);
		return false;
	}

	// 检查文件类型
	if (props.imageOnly) {
		const isImage = file.type.startsWith('image/');
		if (!isImage) {
			ElMessage.error('只能上传图片文件！');
			return false;
		}
	}

	if (props.fileOnly) {
		const isImage = file.type.startsWith('image/');
		if (isImage) {
			ElMessage.error('不能上传图片文件！');
			return false;
		}
	}

	// 检查数量限制
	if (!props.multi && files.value && files.value.length >= props.limit) {
		ElMessage.warning(`最多只能上传 ${props.limit} 个文件`);
		return false;
	}

	if (props.multi && files.value && files.value.length >= props.limit) {
		ElMessage.warning(`最多只能上传 ${props.limit} 个文件`);
		return false;
	}

	return true;
};

/**
 * 上传进度回调
 */
const onProgress = (event: any, file: any) => {
	file.percentage = Math.round((event.loaded * 100) / event.total);
	file.status = 'uploading';

	if (props.multi && file.raw) {
		const existingIndex = files.value.findIndex((f) => f.uid === file.uid);
		const isImage = file.raw.type.startsWith('image/');
		const uploadingFile = {
			name: file.name,
			url: isImage ? URL.createObjectURL(file.raw) : '',
			FileId: null,
			status: 'uploading',
			uid: file.uid,
			percentage: file.percentage,
			isImage: isImage,
			size: file.size,
		};

		if (existingIndex === -1) {
			files.value.push(uploadingFile);
		} else {
			files.value[existingIndex] = uploadingFile;
		}
	}
};

/**
 * 上传成功回调
 */
const onSuccess = (res: any, uploadFile: any) => {
	uploadFile.FileId = res.Id;
	const isImage = uploadFile.raw.type.startsWith('image/');
	uploadFile.url = isImage ? `/api/_file/getfile/${res.Id}?width=150&height=150` : `/api/_file/getfile/${res.Id}`;
	uploadFile.status = isImage ? 'loading' : 'success';

	if (!props.multi) {
		fileValue.value = res.Id;
		if (files.value.length > 0) {
			deletedFiles.value.push(files.value[0].FileId);
			files.value = [];
		}
		files.value.push({
			name: uploadFile.name,
			url: uploadFile.url,
			FileId: res.Id,
			status: uploadFile.status,
			isImage: isImage,
			size: uploadFile.size,
		});
	} else {
		const newFile = {
			name: uploadFile.name,
			url: uploadFile.url,
			FileId: res.Id,
			status: uploadFile.status,
			uid: uploadFile.uid,
			isImage: isImage,
			size: uploadFile.size,
		};

		const uploadingIndex = files.value.findIndex((f) => f.uid === uploadFile.uid);
		if (uploadingIndex !== -1) {
			files.value[uploadingIndex] = newFile;
		} else {
			const existingIndex = files.value.findIndex((f) => f.FileId === res.Id);
			if (existingIndex === -1) {
				files.value.push(newFile);
			} else {
				files.value[existingIndex] = newFile;
			}
		}

		const validFiles = files.value.filter((f) => f.FileId && (f.status === 'success' || f.status === 'loading'));
		const newValue = validFiles.map((item, i) => ({ FileId: item.FileId, Order: i }));

		isUpdatingFromUpload.value = true;
		fileValue.value = newValue;
		setTimeout(() => {
			isUpdatingFromUpload.value = false;
		}, 100);
	}

	ElMessage.success('上传成功');
};

/**
 * 移除文件
 */
const onRemove = (file: any) => {
	if (file.FileId && file.status !== 'uploading') {
		fileApi().deleteFile(file.FileId);
	}

	if (!props.multi) {
		if (file.FileId) {
			deletedFiles.value.push(file.FileId);
		}
		files.value = [];
		fileValue.value = null;
	} else {
		const index = files.value.findIndex((item) => (item.FileId ? item.FileId === file.FileId : item.uid === file.uid));
		if (index > -1) {
			if (file.FileId) {
				deletedFiles.value.push(file.FileId);
			}
			files.value.splice(index, 1);

			const validFiles = files.value.filter((f) => f.FileId);
			fileValue.value = validFiles.map((item, i) => ({
				FileId: item.FileId,
				ID: item.keyID,
				Order: i,
			}));
		}
	}
};

/**
 * 上传错误回调
 */
const onError = (error: any, file: any) => {
	ElMessage.error(`${file.name} 上传失败：${error.message || '未知错误'}`);

	if (props.multi && file.uid) {
		const failedIndex = files.value.findIndex((f) => f.uid === file.uid);
		if (failedIndex !== -1) {
			files.value.splice(failedIndex, 1);
		}
	}
};

/**
 * 删除文件确认
 */
const handleRemove = (file: any) => {
	if (file.status === 'uploading') {
		onRemove(file);
		return;
	}

	ElMessageBox.confirm('确定要删除这个文件吗？', '提示', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning',
	})
		.then(() => {
			onRemove(file);
			ElMessage.success('删除成功');
		})
		.catch(() => {});
};

/**
 * 超出上传限制处理
 */
const onExceed = () => {
	ElMessage.warning(`最多只能上传 ${props.limit} 个文件`);
};

/**
 * 图片加载完成回调
 */
const onImageLoad = (file: any) => {
	if (file.status === 'loading') {
		file.status = 'success';

		if (props.multi) {
			const validFiles = files.value.filter((f) => f.FileId && (f.status === 'success' || f.status === 'loading'));
			const newValue = validFiles.map((item, i) => ({ FileId: item.FileId, Order: i }));

			isUpdatingFromUpload.value = true;
			fileValue.value = newValue;
			setTimeout(() => {
				isUpdatingFromUpload.value = false;
			}, 100);
		}
	}
};

/**
 * 图片加载失败回调
 */
const onImageError = (file: any) => {
	console.warn('图片加载失败，将显示占位符:', file?.FileId);

	if (file) {
		file.status = 'error';
		file.hasError = true;
	}
};

// 暴露方法
defineExpose({
	clearFiles: () => {
		files.value = [];
		fileValue.value = props.multi ? [] : null;
	},
});
</script>

<style lang="scss" scoped>
.upload-media-container {
	width: 100%;
}

.media-list {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	align-items: flex-start;

	@media (max-width: 768px) {
		gap: 8px;
	}
}

.media-item {
	position: relative;
	width: 120px;
	border-radius: 6px;
	overflow: hidden;
	background: #f5f7fa;
	border: 1px solid #e4e7ed;
	flex-shrink: 0;
	transition: all 0.3s ease;

	&:hover {
		border-color: var(--el-color-primary);
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
		transform: translateY(-2px);
	}

	&.is-image {
		height: 120px;
	}

	&.is-file {
		height: auto;
		min-height: 100px;
	}

	.multi-upload & {
		width: 110px;

		&.is-image {
			height: 110px;
		}

		@media (max-width: 768px) {
			width: 100px;

			&.is-image {
				height: 100px;
			}
		}
	}

	.media-wrapper {
		width: 100%;
		height: 100%;
		position: relative;
		display: flex;
		flex-direction: column;
	}

	&.is-uploading {
		.media-wrapper {
			opacity: 0.8;
		}
	}
}

.media-content {
	width: 100%;
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

.img-container {
	position: relative;

	img {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	.media-placeholder {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		width: 100%;
		height: 100%;
		color: var(--el-text-color-placeholder);
		background-color: var(--el-fill-color-lighter);

		i {
			font-size: 24px;
			margin-bottom: 4px;
		}

		span {
			font-size: 11px;
			text-align: center;
			padding: 0 6px;
		}

		&.error-placeholder {
			background-color: var(--el-color-error-light-9);
			color: var(--el-color-error);
			border: 1px dashed var(--el-color-error-light-5);

			i {
				color: var(--el-color-error-light-3);
			}
		}
	}
}

.file-container {
	flex-direction: column;
	padding: 8px;
	gap: 6px;

	.file-thumbnail {
		position: relative;
		width: 48px;
		height: 48px;
		display: flex;
		align-items: center;
		justify-content: center;
		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
		border-radius: 6px;
		margin: 0 auto;

		i {
			font-size: 24px;
			color: #fff;
		}

		.file-ext {
			position: absolute;
			bottom: -4px;
			right: -4px;
			background: var(--el-color-primary);
			color: #fff;
			font-size: 9px;
			font-weight: bold;
			padding: 1px 3px;
			border-radius: 3px;
			border: 1.5px solid #fff;
		}
	}

	.file-info {
		width: 100%;
		text-align: center;

		.file-name {
			font-size: 11px;
			color: var(--el-text-color-primary);
			font-weight: 500;
			white-space: nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
			margin-bottom: 2px;
		}

		.file-size {
			font-size: 10px;
			color: var(--el-text-color-secondary);
		}
	}
}

.upload-progress-mask {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(255, 255, 255, 0.95);
	backdrop-filter: blur(2px);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-direction: column;
	border-radius: 6px;
	animation: fadeIn 0.3s ease-out;
	z-index: 3;

	.progress-content {
		text-align: center;

		.loading-spinner {
			display: flex;
			align-items: center;
			justify-content: center;
			width: 40px;
			height: 40px;

			i {
				font-size: 24px;
				color: #409eff;
			}
		}

		.progress-text {
			display: block;
			margin-top: 6px;
			font-size: 11px;
			color: var(--el-color-primary);
			font-weight: 500;
		}
	}
}

.upload-trigger {
	:deep(.el-upload) {
		width: 120px;
		height: 120px;
		flex-shrink: 0;
	}

	.multi-upload & {
		:deep(.el-upload) {
			width: 110px;
			height: 110px;

			@media (max-width: 768px) {
				width: 100px;
				height: 100px;
			}
		}
	}

	.upload-btn {
		width: 100%;
		height: 100%;
		border: 2px dashed var(--el-border-color);
		border-radius: 6px;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		cursor: pointer;
		transition: all 0.3s ease;
		background: var(--el-fill-color-lighter);

		&:hover {
			border-color: var(--el-color-primary);
			background: var(--el-color-primary-light-9);
			transform: translateY(-2px);
			box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
		}

		i {
			font-size: 28px;
			color: var(--el-text-color-secondary);
			margin-bottom: 6px;
		}

		.upload-text {
			font-size: 12px;
			color: var(--el-text-color-regular);
			font-weight: 500;
		}

		.upload-count {
			font-size: 10px;
			color: var(--el-text-color-secondary);
			margin-top: 3px;
		}
	}
}

.upload-placeholder {
	width: 120px;
	height: 120px;
	border: 2px dashed var(--el-border-color-light);
	border-radius: 6px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--el-fill-color-lighter);

	.placeholder-content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		color: var(--el-text-color-placeholder);

		i {
			font-size: 28px;
			margin-bottom: 6px;
		}

		span {
			font-size: 12px;
		}
	}
}

.item-mask {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(0, 0, 0, 0.6);
	opacity: 0;
	transition: opacity 0.3s ease;
	z-index: 2;

	&:hover {
		opacity: 1;
	}

	.action-icons {
		display: flex;
		gap: 10px;

		.action-btn {
			width: 30px;
			height: 30px;
			display: flex;
			align-items: center;
			justify-content: center;
			color: #fff;
			font-size: 15px;
			cursor: pointer;
			border-radius: 50%;
			background: rgba(255, 255, 255, 0.25);
			backdrop-filter: blur(4px);
			transition: all 0.3s ease;

			&:hover {
				background: rgba(255, 255, 255, 0.4);
				transform: scale(1.1);
			}

			&.delete-btn:hover {
				background: var(--el-color-danger);
			}

			&.preview-btn:hover {
				background: var(--el-color-primary);
			}

			&.download-btn:hover {
				background: var(--el-color-success);
			}
		}
	}
}

.corner-mark {
	position: absolute;
	top: 4px;
	right: 4px;
	background: rgba(0, 0, 0, 0.6);
	color: #fff;
	font-size: 10px;
	padding: 1px 6px;
	border-radius: 10px;
	z-index: 1;
	backdrop-filter: blur(4px);
	font-weight: 500;
}

.file-type-badge {
	position: absolute;
	bottom: 4px;
	left: 4px;
	background: rgba(0, 0, 0, 0.6);
	color: #fff;
	font-size: 10px;
	padding: 1px 6px;
	border-radius: 8px;
	z-index: 1;
	backdrop-filter: blur(4px);

	&.is-image {
		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
	}
}

// 预览对话框样式
.file-preview-dialog {
	.preview-container {
		display: flex;
		justify-content: center;
		align-items: center;
		min-height: 300px;
		background: #fafafa;
		overflow: hidden;

		&.fullscreen-preview {
			min-height: 75vh;
		}

		// 图片预览
		.preview-image {
			max-width: 100%;
			max-height: 65vh;
			object-fit: contain;
		}

		// iframe 预览（PDF、Office）
		.preview-iframe {
			width: 100%;
			height: 65vh;
			border: none;
		}

		// 文本预览
		.preview-text {
			width: 100%;
			height: 65vh;
			overflow: auto;
			background: #fff;
			padding: 16px;

			pre {
				margin: 0;
				font-family: 'Courier New', Courier, monospace;
				font-size: 12px;
				line-height: 1.5;
				white-space: pre-wrap;
				word-wrap: break-word;
				color: var(--el-text-color-primary);
			}

			.loading-text {
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				height: 100%;
				color: var(--el-text-color-secondary);

				i {
					font-size: 28px;
					margin-bottom: 8px;
					color: var(--el-color-primary);
				}

				span {
					font-size: 13px;
				}
			}
		}

		// 视频预览
		.preview-video {
			max-width: 100%;
			max-height: 65vh;
		}

		// 音频预览
		.preview-audio {
			width: 100%;
			max-width: 450px;
		}

		// 不支持预览
		.preview-unsupported {
			width: 100%;
			height: 300px;
			display: flex;
			align-items: center;
			justify-content: center;

			.unsupported-content {
				text-align: center;
				color: var(--el-text-color-secondary);

				i {
					color: var(--el-text-color-placeholder);
					margin-bottom: 12px;
				}

				p {
					margin: 6px 0;
					font-size: 13px;

					&.file-name {
						font-weight: 500;
						color: var(--el-text-color-primary);
						margin-bottom: 16px;
					}
				}
			}
		}
	}

	.preview-footer {
		display: flex;
		justify-content: flex-end;
		gap: 8px;
		padding-top: 8px;
	}
}

// 淡入动画
@keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}
</style>
